package com.moyun.modelclass.view.preview;

import android.content.Context;
import android.opengl.GLES20;
import android.opengl.GLSurfaceView;
import android.opengl.Matrix;
import android.util.AttributeSet;

import java.nio.FloatBuffer;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

public class STLViewss extends GLSurfaceView {

    private final STLRenderer renderer;

    public STLViewss(Context context) {
        super(context);
        setEGLContextClientVersion(2);
        renderer = new STLRenderer();
        setRenderer(renderer);
    }

    public STLViewss(Context context, AttributeSet attrs) {
        super(context, attrs);
        setEGLContextClientVersion(2);
        renderer = new STLRenderer();
        setRenderer(renderer);
    }

    public void setModel(FloatBuffer vertices) {
        renderer.setModel(vertices);
    }

    private static class STLRenderer implements GLSurfaceView.Renderer {

        private FloatBuffer verticesBuffer;
        private final float[] mvpMatrix = new float[16];
        private final float[] projectionMatrix = new float[16];
        private final float[] viewMatrix = new float[16];
        private final float[] modelMatrix = new float[16];

        public void setModel(FloatBuffer vertices) {
            this.verticesBuffer = vertices;
        }

        @Override
        public void onSurfaceCreated(GL10 gl, EGLConfig config) {
            GLES20.glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
            GLES20.glEnable(GLES20.GL_DEPTH_TEST);

            // Initialize shader
            String vertexShaderCode = "uniform mat4 uMVPMatrix;" +
                    "attribute vec4 vPosition;" +
                    "void main() {" +
                    "  gl_Position = uMVPMatrix * vPosition;" +
                    "}";
            String fragmentShaderCode = "precision mediump float;" +
                    "void main() {" +
                    "  gl_FragColor = vec4(0.0, 0.5, 0.0, 1.0);" +
                    "}";

            int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexShaderCode);
            int fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode);

            int program = GLES20.glCreateProgram();
            GLES20.glAttachShader(program, vertexShader);
            GLES20.glAttachShader(program, fragmentShader);
            GLES20.glLinkProgram(program);
            GLES20.glUseProgram(program);

            int positionHandle = GLES20.glGetAttribLocation(program, "vPosition");
            int mvpMatrixHandle = GLES20.glGetUniformLocation(program, "uMVPMatrix");

            GLES20.glEnableVertexAttribArray(positionHandle);
            GLES20.glVertexAttribPointer(positionHandle, 3, GLES20.GL_FLOAT, false, 0, verticesBuffer);

            // Prepare the projection and view transformation
            Matrix.setLookAtM(viewMatrix, 0, 0, 0, -3, 0, 0, 0, 0, 1, 0);
            Matrix.multiplyMM(mvpMatrix, 0, projectionMatrix, 0, viewMatrix, 0);
            Matrix.setIdentityM(modelMatrix, 0);
            Matrix.multiplyMM(mvpMatrix, 0, mvpMatrix, 0, modelMatrix, 0);

            GLES20.glUniformMatrix4fv(mvpMatrixHandle, 1, false, mvpMatrix, 0);
        }

        @Override
        public void onDrawFrame(GL10 gl) {
            GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
            if (verticesBuffer != null) {
                GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, verticesBuffer.limit() / 3);
            }
        }

        @Override
        public void onSurfaceChanged(GL10 gl, int width, int height) {
            GLES20.glViewport(0, 0, width, height);
            float ratio = (float) width / height;
            Matrix.frustumM(projectionMatrix, 0, -ratio, ratio, -1, 1, 3, 7);
        }

        private int loadShader(int type, String shaderCode) {
            int shader = GLES20.glCreateShader(type);
            GLES20.glShaderSource(shader, shaderCode);
            GLES20.glCompileShader(shader);
            return shader;
        }
    }
}

